home *** CD-ROM | disk | FTP | other *** search
/ Windows News 2010 Summer - Disc 1 / WN_Ete2010_CD1.iso / Onglet5 / Weezo / Weezo setup.exe / {code_appDir} / www / login.php < prev    next >
PHP Script  |  2010-05-19  |  53KB  |  1,321 lines

  1. <?php
  2. /**
  3.  * LOGIN
  4.  *
  5.  * login controls : verify password, log user
  6.  * DOESN'T DISPLAY LOGIN FORM:
  7.  * theme login form is included by login.php
  8.  *
  9.  *
  10.  * List of parameters sent to loginForm.php script
  11.  * - $_ENV['users'][] : arrays of user accounts to be displayed (array key is user id)
  12.  *        user data :
  13.  *             ['authenticationMethod'] : user authentication method : 'noAuthentication' or 'password'
  14.  *             ['name'] (optional) : user name. Set to false if both name and user Id must be entered
  15.  *             ['icon'] : user icon file basename (add /gfx/icons/ to have full path)
  16.  *             ['hint'] (optional) : password hint, to be displayed
  17.  * - $userToDisplay () optional : id of selected user (set if an user name has been passed in get args or if a wrong password has been typed),
  18.  *             (set to 0 (zero) if login+password) input must be selected)
  19.  * - $userAndPasswordMethod : true if login+password form has been used
  20.  * - $wrongPasswordSent : true if a wrong password has been entered
  21.  * - $wrongUserSent : true if a non-existing user name has been entered
  22.  * - $hiddenUsers : true if at least one hidden user account exists => user name+password form must be displayed
  23.  *
  24.  *
  25.  * PHP version 5
  26.  *
  27.  * LICENSE: This source file is subject to version 3.0 of the PHP license
  28.  * that is available through the world-wide-web at the following URI:
  29.  * http://www.php.net/license/3_0.txt.  If you did not receive a copy of
  30.  * the PHP License and are unable to obtain it through the web, please
  31.  * send a note to license@php.net so we can mail you a copy immediately.
  32.  *
  33.  * @category   NA
  34.  * @package    NA
  35.  * @author     Nicolas Bruley / Peer 2 World <contact@weezo.net>
  36.  * @copyright  2005-2009 Nicolas Bruley / Peer 2 World
  37.  * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
  38.  * @version    CVS: $Id:$
  39.  * @link       http://www.weezo.net
  40.  * @since      File available since Release 1.0.0
  41.  */
  42. require_once(INCLUDE_DIR.'initFunctions.php');
  43. require_once(INCLUDE_DIR.'outputFunctions.php');
  44. define('CONNECTION_ATTEMPTS_CLEANUP_TIME', 10); // connectionAttempts.txt entries cleanup time (in days)
  45. define('LOGIN_TOKEN_LIFETIME', 60); // Login token lifetime, in seconds
  46. define('LOGIN_TOKEN_CHECK_IP', false); // Set to true to check client connects with same IP that the IP used for connection to central authentication server (disabled)
  47.  
  48. $nbWrongPasswordTyped=0; // Global var, number of wrong password typed by an IP adress in passwordCheckBanPeriod time interval
  49. $userToDisplaySeqNumber=0; // Sequential user number on login page
  50.  
  51.  
  52. /**
  53.  * @desc function called on successful user login: load parameters and display left panel and 1st resource
  54.  *             if $userConfigFileName is provided, load user from filename
  55.  * @param string $userId: user id
  56.  * @param string $userConfigFileName (optional): user configuration file
  57.  * @return void
  58. */
  59. function userLoad($userId,$userConfigFileName=false){
  60.     if(!$userId && !$userConfigFileName) die('User ID not found');
  61.  
  62.     // Temp store session data as $_SESSION will be erased by wSession_start, and some usefull data may already have been stored into (cfGSetVar)
  63.     if(@$_SESSION) $tmp=$_SESSION;
  64.  
  65.     // Destroy previous session if existing (might have been started by /index.php)
  66.     if(isset($_ENV['wSession'])) {
  67.         wSession_write_close();
  68.         unset($_ENV['wSession']);
  69.     }
  70.     if(isset($_COOKIE['WSESSID'])) unset($_COOKIE['WSESSID']);
  71.  
  72.     // Start session
  73.     wSession_start();
  74.  
  75.     if(isset($tmp)) $_SESSION=$tmp;
  76.  
  77.     // Get configuration (to ensure user exists and retreive actual id)
  78.     $uc=new WUserConfig(($userId)?$userId:$userConfigFileName);
  79.     if(!$uc->isValid()) die('User ID not found');
  80.  
  81.     // Set logged user id
  82.  
  83.     // If user id not passed, find user from filename
  84.     $_SESSION['user']=$uc->getData();
  85.     $userId=$_SESSION['userId']=$_SESSION['user']['id']=$uc->id();
  86.  
  87.  
  88.  
  89.     /**
  90.      * Last security check: check referer (XSRF protection)
  91.      */
  92.     $headers=getallheaders();
  93.  
  94.     if(cfIPFilterIsset($_SESSION['user']) && isset($headers['Referer'])) {
  95.         $refererURL=parse_url($headers['Referer']);
  96.         if(isset($refererURL['host'])){
  97.  
  98.             // Allow redirection from "DNS" server
  99.             if('http://'.$refererURL['host']!=DNS_SITE){
  100.                 // Else, get IP from host name
  101.                 if($refererURL['host']=='localhost') $refererURL['host']='127.0.0.1';
  102.                 if(!cfIsIP($refererURL['host'])) $refererURL['host']=gethostbyname($refererURL['host']);
  103.  
  104.                 // If referer IP could not be retreived from referer hostname or referer IP is not allowed to connect this account, abort
  105.                 if(!cfIsIP($refererURL['host']) || !cfIPFilterCheck($_SESSION['user'],$refererURL['host'])){
  106.                     wSession_destroy();
  107.                     die('unauthorized redirection');
  108.                 }
  109.             }
  110.         }
  111.     }
  112.  
  113.  
  114.     // Mobile login
  115.     if(@$_POST['mobile']) cfGSetVar('forceMobile',1);
  116.  
  117.     // Server port (override general.ini value as alternatePort may have been used)
  118.     if(@$_SERVER['SERVER_PORT']){
  119.         cfGSetVar('serverPort',$_SERVER['SERVER_PORT']);
  120.         cfGSetVar('protocol',($_SERVER['SERVER_PORT']==443)?'https':'http');
  121.     }
  122.  
  123.     // Standalone resource: integrate publishToken
  124.     if($userId==='standalone') {
  125.         $_SESSION['user']['publishToken']=$_GET['publishToken'];
  126.         // Also set in a cookie so if (weezo) session ends, user automatically re-logs
  127.         setcookie('weezoPublishToken',$_GET['publishToken'],(time()+3600));
  128.     }
  129.  
  130.     // Load user resource info
  131.     $nbResourcesLoaded=ifLoadUserResources();
  132.  
  133.     $_SESSION['accountIP'] = $_SERVER['REMOTE_ADDR'];
  134.     $_SESSION['activeResourceId']=0;
  135.  
  136.     // If user has requested a specific theme, replace user theme
  137.     if(isset($_POST['userSelectedTheme']) && $_POST['userSelectedTheme']!='' && cfGGetVar('allowUserThemeChange'))
  138.         cfUSetVar('theme',cfUTF8Decode($_POST['userSelectedTheme']));
  139.  
  140.     // Get user screen size
  141.     if (isset($_POST['userScreenWidth'])) cfGSetVar('userScreenWidth',$_POST['userScreenWidth']);
  142.     if (isset($_POST['userScreenHeight'])) cfGSetVar('userScreenHeight',$_POST['userScreenHeight']);
  143.  
  144.     // If a resource is requested as 1st page startup
  145.     if(isset($_GET['res'])){
  146.         foreach (cfResourcesGetUser() as $k=>$v) if(isset($v['name']) && $v['name']==urldecode($_GET['res'])){
  147.             cfGSetVar('resourceDisplayAtStartup',$k);
  148.             break;
  149.         }
  150.     }
  151.  
  152.     // If browser has a dedicated theme, apply it and forbid further changes
  153.     if(cfBGetVar('theme')) {cfGSetVar('theme',cfBGetVar('theme'));cfGSetVar('allowUserThemeChange',false);}
  154.  
  155.     // else if mobile device, use mobile theme
  156.     elseif (cfIsMobile()) {cfGSetVar('theme','mobile');cfGSetVar('allowUserThemeChange',false);}
  157.     if(!cfBGetVar('frames')) cfGSetVar('noPopup',true);
  158.  
  159.     // Get server (this) host name
  160.     if (isset($_POST['serverExternalHost'])) cfGSetVar('hostName',((isset($_SERVER['HTTPS']))?'https':'http').'://'.$_POST['serverExternalHost']);
  161.  
  162.     // Get visitor's host name
  163.     if(cfGGetVar('getVisitorHostName')){if($host=@gethostbyaddr($_SERVER['REMOTE_ADDR'])==$_SERVER['REMOTE_ADDR']) $host='';}    else $host='';
  164.     cfUSetVar('host',$host);
  165.  
  166.     // If single user account type, verify that this user is not already logged
  167.     $nbConnected=0;
  168.     $maxConnected=cfUGetVar('maxSimultaneousUsers');
  169.     if(cfUGetVar('accountType')=='singleUser') $maxConnected=1;
  170.     if($maxConnected){
  171.         $sessionFiles=glob(cfAppDataDir().'/sessiondata/sess_*');
  172.         // Browse sessions
  173.         foreach ($sessionFiles as $filename) if(substr($filename,5)!=wSession_id()){
  174.             if(cfGGetVar('sessionHandler')=='memory') $sessData=cfUnserializeSession(@cfMGetVar('weezoS'.substr(basename($filename),1),true));
  175.             else $sessData=cfUnserializeSession(file_get_contents($filename));
  176.             if(isset($sessData['user']['id']) && $sessData['user']['id']==cfUGetVar('id')) {
  177.                 $nbConnected++;
  178.                 // If single user and loginDisconnectPreviousUser, destroy previous connection
  179.                 if(cfUGetVar('accountType')=='singleUser' && cfGGetVar('loginDisconnectPreviousOnConflict')){
  180.                     if(cfGGetVar('sessionHandler')=='memory') @cfMUnsetVar('weezoS'.substr(basename($filename),1));
  181.                     else @unlink($filename);
  182.                     break;
  183.                 }
  184.                 // If more than max connected users, abort
  185.                 if($nbConnected>=$maxConnected){
  186.                     cfAsyncHeader();
  187.                     if($maxConnected==1) echo cfAsyncXMLJSaction('alert("'.cfCaption('loginAlreadyConnected',cfUTF8Encode(cfUGetVar('name'))).'")');
  188.                     else echo cfAsyncXMLJSaction('alert("'.cfCaptionJS('loginMaxUsersReached').'")');
  189.                     echo cfAsyncXMLJSaction('W.location.reload()');
  190.                     echo cfAsyncFooter();
  191.                     wSession_destroy();
  192.                     exit;
  193.                 }
  194.             }
  195.         }
  196.     }
  197.  
  198.     // Set user language
  199.     // First use preference's language from single users
  200.     if(cfUGetVar('accountType')=='singleUser' && cfMIssetVar('weezoLng'.cfUGetVar('language'))) cfGSetVar('language',cfUGetVar('language'));
  201.  
  202.     // Check if user name/pseudo must be requested
  203.     if(cfUGetVar('accountType')=='named'){
  204.         // If pseudo passed as POST var
  205.         if(isset($_POST['userPseudo']) && $_POST['userPseudo']){
  206.             cfUSetVar('pseudo',cfUTF8Decode($_POST['userPseudo']));
  207.         }
  208.         // If pseudo passed as GET var
  209.         elseif(isset($_GET['userPseudo']) && $_GET['userPseudo']){
  210.             cfUSetVar('pseudo',cfUTF8Decode($_GET['userPseudo']));
  211.         }
  212.         else{
  213.             cfGSetVar('requestUserPseudo',true);
  214.             // Redirect to login page
  215.             if(cfIsAsync()){
  216.                 echo cfAsyncHeader();
  217.                 echo cfAsyncXMLJSaction('maskHide()');
  218.                 echo cfAsyncXMLJSaction('loginPseudoGet("'.addslashes(cfUTF8Encode(cfUGetVar('name'))).'")');
  219.                 echo cfAsyncFooter();
  220.             }
  221.             else {
  222.                 ?>
  223. <body onload="document.connectForm.submit()">
  224. <form name="connectForm" action="/index.php" method="GET" enctype="multipart/form-data" style="display:none"></form>
  225. </body>
  226.                 <?php
  227.             }
  228.             exit;
  229.         }
  230.     }
  231.     // Set user as logged
  232.     $_SESSION['userLogged']=true;
  233.  
  234.     // send info to application and display main page
  235.     loginFinish();
  236. }
  237.  
  238. /**
  239.  * @desc finish login process
  240.  *         - Send info to application
  241.  *         - Log connection to database
  242.  *         - Load main page
  243.  *
  244.  */
  245. function loginFinish(){
  246.     // Set user as logged
  247.     $_SESSION['userLogged']=true;
  248.     $_SESSION['connectionTime']=time();
  249.     cfGSetVar('connectionTime',time());
  250.  
  251.     // Write connection in log and activity panel
  252.     cfLog(cfUTF8Decode(cfCaption('loginNewConnection',cfUTF8Encode(cfUGetVar('name').((cfUGetVar('pseudo'))?' - '.cfUGetVar('pseudo'):'')),false,false,true)),LOG_INF);
  253.  
  254.     // If direct resource access, set resource name as user name, for display in activity panel
  255.     if(cfUGetVar('id')=='standalone' && !cfUGetVar('name')){
  256.         $res=new WResConfig(@$_SESSION['res'][0]['id']);
  257.         cfUSetVar('name',@$res->name());
  258.         cfUSetVar('icon','blankIcon.gif');
  259.     }
  260.  
  261.     // inform application that a new user logged in
  262.     $logString='log newLogged="'.wSession_id().
  263.         '" name="'.str_replace('"','',cfUGetVar('name')).
  264.         '" id="'.cfUGetVar('id').
  265.         '" pseudo="'.str_replace('"','',cfUGetVar('pseudo')).
  266.         '" icon="'.cfUGetVar('icon').
  267.         '" IP="'.$_SESSION['accountIP'].
  268.         '" filename="'.basename(cfUGetVar('configFilename')).
  269.         '" host="'.cfUGetVar('host').
  270.         '" audioProfile="'.cfUGetVar('audioProfile').
  271.         '" browser="'.cfBGetVar('name').'"';
  272.  
  273.     // List user's chat resources, and check if user has webcam
  274.     $chat=''; $webcam=false;
  275.     foreach (WEnv::user()->getResources() as $rid=>$rfilename){
  276.         if($res=cfMGetVar('weezoResData'.$rid)){
  277.             if($res['type']=='webcam' && $res['subType']=='chat') $chat.=(($chat)?',':'').$rid.'/'.    $rfilename;
  278.             if($res['type']=='webcam' && $res['subType']=='std') $webcam=true;
  279.         }
  280.     }
  281.     if($chat) $logString.=' chatResourceFilenames="'.$chat.'"';
  282.     if($webcam) $logString.=' needWebcam="true"';
  283.  
  284.  
  285.     // Timeout detection margin
  286.  
  287.     // Increase for mobiles
  288.     if(cfIsMobile('iPhone')) $logString.=' inactivityTimeBeforeDisconnect="'.(5*cfGGetVar('inactivityTimeBeforeDisconnect')).'"';
  289.     elseif(cfUGetVar('id')=='standalone') {
  290.         $res=@$_SESSION['res'][0];
  291.         // Increase timeout detection margin for non-server-pinging external resources
  292.         if(@$res['type']=='misc' || (@$res['type']=='website' && @$res['subType']=='html')) $logString.=' inactivityTimeBeforeDisconnect="'.floor(3*cfGGetVar('inactivityTimeBeforeDisconnect')).'"';
  293.         // and decrease it for other published resources
  294.         else $logString.=' inactivityTimeBeforeDisconnect="'.floor(0.5*cfGGetVar('inactivityTimeBeforeDisconnect')).'"';
  295.     }
  296.  
  297.     cfServerSendCommand($logString);
  298.  
  299.     // Log information in statistics database
  300.     require_once(INCLUDE_DIR.'databaseFunctions.php');
  301.     if(!cfUGetVar('invisible')) dbLogNewConnection();
  302.  
  303.     // Monitor event
  304.     if(!cfUGetVar('invisible')) cfLogEvent(cfCaption('loginNewConnection',cfUTF8Encode(cfUGetVar('name')),false,false,true),EVENT_CONNECTION,S_EVENT_LOGIN,cfUGetVar('id'));
  305.  
  306.     // Redirect to login page
  307.     if(cfIsAsync()){
  308.         cfAsyncHeader();
  309.         echo cfAsyncXMLJSaction('maskHide()');
  310.         // Send login cookie to Wii
  311.         if(cfIsWII()){
  312.             echo cfAsyncXMLJSaction('var exp=new Date();exp.setTime(exp.getTime() + (365*24*3600000));document.cookie="weezoUser='.cfUGetVar('id').'; expires="+exp.toGMTString();');
  313.             if(cfUGetVar('authenticationMethod')=='password')
  314.                 echo cfAsyncXMLJSaction('var exp=new Date();exp.setTime(exp.getTime() + (365*24*3600000));document.cookie="weezoAuth='.sha1(cfUGetVar('password')).'; expires="+exp.toGMTString();');
  315.         }
  316.         // Do connect
  317.         echo cfAsyncXMLJSaction('loginConnect()');
  318.         echo cfAsyncFooter();
  319.     }
  320.     else {
  321.         // Set URL where user will be redirected
  322.         $connectedURL='/index.php';
  323.  
  324.         // If user is re-login to a published which session has terminated, redirect to page he was
  325.         if(isset($_ENV['publishTokenBeforeLogoutURI'])) $connectedURL=$_ENV['publishTokenBeforeLogoutURI'];
  326. ?>
  327. <head>
  328. <script type="text/javascript">
  329. function doLog(){
  330. <?php
  331. // Manually set cookie (IE Workaround on token identification)
  332. if(!cfGGetVar('userScreenWidth')) {?>
  333. document.getElementsByName("userScreenWidth")[0].value=screen.width;
  334. document.getElementsByName("userScreenHeight")[0].value=screen.height;
  335. <?php
  336. }
  337. if(!cfGGetVar('hostName')) {?> document.getElementsByName("serverExternalHost")[0].value=document.location.host; <?php }
  338. ?>
  339. document.connectForm.submit();
  340. }
  341. </script>
  342. </head><body onload="doLog()">
  343. <form name="connectForm" action="<?php echo $connectedURL; ?>" method="GET" enctype="multipart/form-data" style="display:none">
  344. <?php
  345. // IE Workaround: cookie sometimes cannot be set at this step (when using login token)
  346. // => pass session id in GET so cookie is set at next page display (by security.php)
  347.         if(!isset($_COOKIE) || !count($_COOKIE)) echo '<input name="WSESSID" value="'.wSession_id().'">';
  348.         if(!cfIsWII()) echo '<input name="loginOK" value="true">';
  349.         if(!cfGGetVar('userScreenWidth')) echo '<input type="text" name="userScreenWidth" value=""><input type="text" name="userScreenHeight" value="">';
  350.         if(!cfGGetVar('hostName')) echo '<input type="text" name="serverExternalHost" value="">';
  351.         echo '</form></body>';
  352.     }
  353.     cfDebugSingle(@$_ENV['wSession']['state']);
  354.     cfDebugSingle(@$_ENV['wSession']['id']);
  355.     wSession_write_close();
  356.     cfDebugSingle(cfMIssetVar('wSessionLocked_'.@$_ENV['wSession']['id']));
  357.     cfDebugSingle('log finished');
  358.     exit;
  359. }
  360.  
  361. /**
  362.  * @desc finish loggin users who need name/pseudo
  363.  *
  364.  */
  365. function userLoadNamedUser(){
  366.     // User canceled
  367.     if($_POST['userPseudo']=='*weezoCancel*'||$_POST['userPseudo']=='undefined') {
  368.         wSession_destroy();
  369.         if(isset($_POST['asyncRequest'])){
  370.             echo cfAsyncHeader();
  371.             echo cfAsyncXMLJSaction('D.connectForm.method="POST";loginConnect()');
  372.             echo cfAsyncFooter();
  373.             exit;
  374.         }
  375.         unset($_POST);
  376.         return;
  377.     }
  378.     cfUSetVar('pseudo',cfUTF8Decode($_POST['userPseudo']));
  379.     cfGSetVar('requestUserPseudo',false);
  380.     // send info to application and display main page
  381.     loginFinish();
  382. }
  383.  
  384. /**
  385.  * @return string ID or false if not found
  386.  * @param string $name : user name
  387.  * @desc Return user id (number) from user name. Return -1 if not found
  388. */
  389. function userIdFromName($name){
  390.     foreach ($_ENV['users'] as $key=>$value) if($value['name']==$name) return $key;
  391.     return false;
  392. }
  393.  
  394. /**
  395.  * @return bool : true if OK
  396.  * @param string $userId : user id
  397.  * @param string $password : password
  398.  * @desc verify $userId and $password. Return true if OK, false if not OK (in this case, wait for a few seconds)
  399. */
  400. function verifyPassword($userId, $password){
  401.     global $wrongPasswordSent;
  402.     global $securityEvent;
  403.  
  404.  
  405.     //if user's authentication method is password
  406.     if($_ENV['users'][$userId]['authenticationMethod']=='password'){
  407.         // Decrypt RSA crypted password
  408.         $decrypted=cfRSADecrypt($password,$wasCiphered);
  409.  
  410.         // Parse return string
  411.         // Return string (decrypt) format : ip=XXX/password/ts=YYY/
  412.         // where XXX is iptolong ip adress and YYY is timestamp
  413.         if($wasCiphered){
  414.             $timestamp=substr($decrypted,strrpos($decrypted,'/ts=')+4);$timestamp=substr($timestamp,0,strpos($timestamp,'/'));
  415.             $longip=substr($decrypted,strpos($decrypted,'ip=')+3);$longip=substr($longip,0,strpos($longip,'/'));
  416.             $password=substr($decrypted,strpos($decrypted,'/',strpos($decrypted,'ip='))+1);$password=substr($password,0,strrpos($password,'/ts='));
  417.         }
  418.  
  419.         // Check client ip adress
  420.         if($wasCiphered && $_SERVER['REMOTE_ADDR']!=long2ip($longip) && !cfGGetVar('disableClientSessionIPControl')){
  421.             $securityEvent.='Password check: incorrect client IP adress error';
  422.             setWrongPasswordTyped();
  423.             return false;
  424.         }
  425.  
  426.         // Check timestamp (allow a 60 seconds difference (default) to cover transmission and ciphering time
  427.         if($wasCiphered && abs(((int)microtime(true))-$timestamp)>((cfGGetVar('RSAAuthorizedDelay'))?cfGGetVar('RSAAuthorizedDelay'):20)){
  428.             $securityEvent.='Password check: excessive time shift error<br>Modify "RSAAuthorizedDelay" value in data/general.ini';
  429.             return false;
  430.         }
  431.  
  432.         // If password is sent unencrypted but encryption was required, refuse
  433.         if (0 /* !$wasCiphered && cfGGetVar('protocol')=='http' &&
  434.                 cfGGetVar('encryptPassword') && (!cfGGetVar('disablePasswordCipheringForSlowJSDevices') || !cfBGetVar('slowJS'))*/){
  435.             cfLog('login.php: unencrypted password sent. Connection refused',LOG_ER);
  436.             $securityEvent.='Password check: encrypted password not found';
  437.             return false;
  438.         }
  439.  
  440.         // Correct password typed
  441.         if(md5($password)==$_ENV['users'][$userId]['password']) {
  442.             setRightPasswordTyped();
  443.             return true;
  444.         }
  445.         // Wrong password typed
  446.         else {
  447.             setWrongPasswordTyped();
  448.             sleep(cfGGetVar('waitTimeBetweenLoginAttemtps'));
  449.             cfLog('login.php: wrong password typed for '.$_ENV['users'][$userId]['name'].' account',LOG_DBG);
  450.             $wrongPasswordSent=true;
  451.             return false;
  452.         }
  453.     }
  454.     elseif($_ENV['users'][$userId]['authenticationMethod']=='noAuthentication') return true; // Password typed on a passwordless account
  455.     cfLog('login.php: unknown authentification method in.usr file, cannot log in'.$userId.' account',LOG_ER);
  456.     $securityEvent.='Password check: unknown error';
  457.     $wrongPasswordSent=true;
  458.     return false;
  459. }
  460.  
  461. /**
  462.  * @desc Validate an external authentication request, and deliver an authentication token if all OK
  463.  *
  464.  * @param string $authenticationToken: encrypted login & pwd
  465.  * @param string $restrictSource: true to restrict external authentication to weezo.net & weezo.info domains
  466.  */
  467. function requestLoginToken($authenticationToken, $restrictSource=true){
  468. /*  Test / debug
  469.     $restrictSource=false;
  470.     $clear=array('user='.base64_encode(cfUTF8Encode('test')),'password='.base64_encode(''),'ip='.'127.0.0.1');
  471.     $clear[]='rnd='.substr(md5(rand()),5,30);
  472.     shuffle($clear);
  473.  
  474.     if(!($regInfo=cfIsRegistered())) die();
  475.     $key=base64_decode($regInfo['regKey']);
  476.     $iv='';for($i=0;$i<8;$i++) $iv.=chr(rand(0,255));
  477.     $authenticationToken=mcrypt_encrypt(MCRYPT_TRIPLEDES,$key,implode('&',$clear),MCRYPT_MODE_CBC,$iv);
  478.  
  479.     $authenticationToken=base64_encode($authenticationToken.$iv);
  480. */
  481.  
  482.     ignore_user_abort(true);
  483.  
  484.     // Restrict source to weezo.net/weezo.info servers
  485.     if($restrictSource && $_SERVER['REMOTE_ADDR']!='87.106.108.74' && $_SERVER['REMOTE_ADDR']!=gethostbyname('weezo.net') && $_SERVER['REMOTE_ADDR']!=gethostbyname('weezo.info')) die();
  486.  
  487.     // Verify user is registered
  488.     if(!($regInfo=cfIsRegistered())) die();
  489.     $key=base64_decode($regInfo['regKey']);
  490.  
  491.     // Public key request
  492.     if($authenticationToken=='getRSAPK') {
  493.         $RSAKeyPair = cfRSALoadKeyPair();
  494.         if(isset($RSAKeyPair['maxDigits']) && isset($RSAKeyPair['modulo']) && isset($RSAKeyPair['publicExponent']))
  495.             die('RSAPK/'.$RSAKeyPair['maxDigits'].'/'.$RSAKeyPair['modulo'].'/'.$RSAKeyPair['publicExponent'].'/'.$RSAKeyPair['keyLength']);
  496.         else
  497.             die();
  498.     }
  499.  
  500.     // Decrypt token
  501.     $token=base64_decode(str_replace(' ','+',$authenticationToken));
  502.     $iv=substr($token,-8); $token=substr($token,0,strlen($token)-8);
  503.     $clear=@mcrypt_decrypt(MCRYPT_TRIPLEDES,$key,$token,MCRYPT_MODE_CBC,$iv);
  504.     @parse_str($clear,$args);
  505.  
  506.  
  507.     /**
  508.      * Check decrypted token format
  509.      */
  510.     if((!isset($args['RSAToken']) && (!isset($args['user'])||!isset($args['password'])))||!isset($args['ip'])) die();
  511.  
  512.     // Client browser encrypted password with RSA public key: decrypt
  513.     if(isset($args['RSAToken'])){
  514.         $decrypted=cfRSADecrypt('rsa:'.$args['RSAToken']);
  515.         @parse_str($decrypted,$args2);
  516.  
  517.         // Verify it contains user and password
  518.         if(!isset($args2['user']) || !isset($args2['password'])) die();
  519.         $user=$args2['user'];
  520.         $password=$args2['password'];
  521.     }
  522.  
  523.  
  524.  
  525.     // Check if client's IP is not banned for excessive attempts
  526.     //if(isBannedIP($args['ip'])) die('maxAttempts');
  527.  
  528.     // Verify user's existence
  529.     if(!isset($user)) $user=cfUTF8Decode(base64_decode($args['user']),true,false,false);
  530.  
  531.     if(!($userId=userIdFromName($user))) die('loginFailed');
  532.  
  533.  
  534.     // Verify IP is allowed to connect to this user
  535.     if(!cfIPFilterCheck($_ENV['users'][$userId],$args['ip'])) die('loginFailed');
  536.  
  537.     // Check password
  538.     if(!isset($password)) $password=(base64_decode($args['password']));
  539.     if($_ENV['users'][$userId]['authenticationMethod']=='password' && md5($password)!=$_ENV['users'][$userId]['password']) die('loginFailed');
  540.  
  541.     // Generate login token id
  542.     $loginToken=''; for($i=0;$i<16;$i++) $loginToken.=chr(rand(0,255)); $loginToken=base64_encode($loginToken);
  543.  
  544.     // Save login token to memory
  545.     $loginTokens=cfMGetVar('loginTokens');
  546.     $loginTokens[$loginToken]=$userId.'/'.$args['ip'].'/'.time();
  547.     cfMSetVar('loginTokens',$loginTokens);
  548.     // All OK: generate login token
  549.     die('loginToken='.$loginToken.(($_ENV['users'][$userId]['accountType']=='named')?'&requestPseudo=1':''));
  550. }
  551.  
  552. /**
  553.  * @desc Check login token validity, and if OK, log user in
  554.  *
  555.  * @param string $loginToken
  556.  */
  557. function checkLoginToken($loginToken){
  558.     $loginToken=str_replace(' ','+',$loginToken);
  559.  
  560.     // Check for passed token in valid tokens list
  561.     $loginTokens=cfMGetVar('loginTokens');
  562.     if(!$loginTokens) {
  563.         //cfVarDump(cfMGetVar('loginTokens',true));
  564.         exit;
  565.     }
  566.     if(!isset($loginTokens[$loginToken])) die(cfCaption('loginForbiddenAccess').'no token found');
  567.  
  568.     // Extract user id and ip
  569.     list($userId,$ip,$timestamp)=explode('/',$loginTokens[$loginToken]);
  570.  
  571.     // Remove from valid tokens list
  572.     unset($loginTokens[$loginToken]);
  573.     cfMSetVar('loginTokens',$loginTokens);
  574.  
  575.  
  576.     // Check token is still valid
  577.     if(time()>$timestamp+LOGIN_TOKEN_LIFETIME) die(cfCaption('loginForbiddenAccess').' lt');
  578.  
  579.     // Check user id is valid
  580.     if(!isset($_ENV['users'][$userId])) die(cfCaption('loginForbiddenAccess').' no user');
  581.  
  582.     // Check token IP matches with client IP
  583.     if(LOGIN_TOKEN_CHECK_IP && $ip!=$_SERVER['REMOTE_ADDR']) {
  584.         if($ip!='0') die(cfCaption('loginForbiddenAccess').' ip nok:'.$ip.'<>'.$_SERVER['REMOTE_ADDR']);
  585.     }
  586.  
  587.     // Check user pseudo is OK
  588.     if($_ENV['users'][$userId]['accountType']=='named' && !isset($_GET['userPseudo']) && !isset($_POST['userPseudo'])) die(cfCaption('loginForbiddenAccess').' no pseudo');
  589.  
  590.     // All OK, proceed to login
  591.     userLoad($userId);
  592. }
  593.  
  594. /**
  595.  * @desc Resource-only login through publishToke
  596.  *
  597.  */
  598. function publishTokenLogin(){
  599.     require_once(INCLUDE_DIR.'explorerFunctions.php');
  600.     $tokenList=efTokensRead();
  601.  
  602.     // If publishToken is retreived from cookie
  603.     if(!isset($_GET['publishToken'])) {
  604.         $_GET['publishToken']=$_COOKIE['weezoPublishToken'];
  605.     }
  606.  
  607.     // Check token
  608.     $found=0;
  609.     foreach (cfMGetVar('weezoResourcesList') as $id=>$filename){
  610.         $res=cfMGetVar('weezoResData'.$id);
  611.         if(isset($res['publishToken']) && $res['publishToken']==$_GET['publishToken']) {
  612.             $found=1;
  613.             break;
  614.         }
  615.     }
  616.     // If no matching resource found, die
  617.     if(!$found){
  618.         // Remove publish token if set (so error page won't return to login)
  619.         if(isset($_COOKIE['weezoPublishToken'])){
  620.             unset($_COOKIE['weezoPublishToken']);
  621.             @setcookie('weezoPublishToken','',(time()-3600));
  622.         }
  623.  
  624.         require_once(INCLUDE_DIR.'outputFunctions.php');
  625.         outDisplayErrorPage(cfCaption('keyError'));
  626.     }
  627.  
  628.     // Set theme
  629.     if(isset($_GET['theme'])) $_POST['userSelectedTheme']=$_GET['theme'];
  630.  
  631.     userLoad('standalone');
  632. }
  633.  
  634. /**
  635.  * @desc check if user's IP is within exessive connections attempts list, stored in data/connectionAttempts.txt file
  636.  *         update $nbWrongPasswordTyped global var
  637.  * @return boolean : true if IP has typed more than passwordCheckMaxAttempts wrong passwords in passwordCheckBanPeriod minutes IPs list, false if not
  638.  *
  639.  */
  640. function isBannedIP($checkedIP=false){
  641.     global $nbWrongPasswordTyped;
  642.     static $passwordCheckMaxAttempts;
  643.  
  644.     if(!isset($passwordCheckMaxAttempts)) {
  645.         $passwordCheckMaxAttempts=cfGGetVar('passwordCheckMaxAttempts');
  646.         $passwordCheckBanPeriod=cfGGetVar('passwordCheckBanPeriod');
  647.     }
  648.  
  649.     if(!cfGGetVar('passwordCheckMaxAttempts') || !file_exists(cfAppDataDir().'/connectionAttempts.txt')) return false;
  650.  
  651.     if(!$checkedIP) $checkedIP=$_SERVER['REMOTE_ADDR'];
  652.  
  653.     $needSave=false; $nbWrongPasswordTyped=0;
  654.  
  655.     // Browse history
  656.     $ipList=parse_ini_file(cfAppDataDir().'/connectionAttempts.txt',false);
  657.     foreach ($ipList as $time=>$ip){
  658.         // Clean old entries{
  659.         if(floor($time)+CONNECTION_ATTEMPTS_CLEANUP_TIME*3600*24<time()) {
  660.             unset($ipList[$time]);
  661.             $needSave=true;
  662.         }
  663.         // Count appliable entries
  664.         if($passwordCheckMaxAttempts>0 && $ip==$checkedIP && (floor($time)+$passwordCheckBanPeriod*60>time())) $nbWrongPasswordTyped++;
  665.         // Reset counter on successfull password typed
  666.         if($ip=='OK'.$checkedIP) $nbWrongPasswordTyped=0;
  667.     }
  668.     // Save changes if cleaned items
  669.     if($needSave) cfWriteIniFile($ipList,cfAppDataDir().'/connectionAttempts.txt',false);
  670.     if($nbWrongPasswordTyped>=cfGGetVar('passwordCheckMaxAttempts')) return true;
  671.     return false;
  672. }
  673.  
  674. /**
  675.  * @desc add entry in data/connectionAttempts.txt file
  676.  * @return void
  677.  *
  678.  */
  679. function setWrongPasswordTyped(){
  680.     global $nbWrongPasswordTyped;
  681.     if(!cfGGetVar('passwordCheckMaxAttempts')) return;
  682.     cfAppendTextToFile(microtime(true).' = '.$_SERVER['REMOTE_ADDR'],cfAppDataDir().'/connectionAttempts.txt',false);
  683.     $nbWrongPasswordTyped++;
  684.     if($nbWrongPasswordTyped>=cfGGetVar('passwordCheckMaxAttempts')){
  685.         cfAsyncHeader();
  686.         echo cfAsyncXMLJSaction('wl.goURL()');
  687.         die(cfAsyncFooter());
  688.     }
  689. }
  690.  
  691. /**
  692.  * @desc add right password entry in data/connectionAttempts.txt file
  693.  * @return void
  694.  *
  695.  */
  696. function setRightPasswordTyped(){
  697.     if(!cfGGetVar('passwordCheckMaxAttempts')) return;
  698.     cfAppendTextToFile(microtime(true).' = OK'.$_SERVER['REMOTE_ADDR'],cfAppDataDir().'/connectionAttempts.txt',false);
  699. }
  700.  
  701. /**
  702.  * @desc echo hidden login form and javascript function used for RSA password encryption
  703.  * @param boolean $encryptionAnimation : true if lock icon animation should be played on encryption
  704.  * @param boolean $waitCursor : true if a wait cursor is displayed while loginForm is being submitted
  705.  * @return  void
  706.  *
  707.  *         "startEncryption" script must always be called by loginFrom.php scripts
  708.  *         It must be called within <body> node as it includes HTML code (unless $encryptionAnimation is set to false)
  709.  *        JS function encryptPassword must be called on form submit, with password node as parameter
  710.  *
  711.  *         JS Script description : cipher password, and submit login form and optionnaly play animation
  712.  *
  713.  */
  714. function includeloginFormAndScripts($encryptionAnimation=true, $waitCursor=true){
  715.     /**
  716.      * Page reload form
  717.      */
  718.     echo '<form name="connectForm" action="/index.php" method="GET" enctype="multipart/form-data" style="display:none">';
  719.     if(!cfIsWII()) echo '<input name="loginOK" value="true">';
  720.     echo '</form>';
  721.  
  722.     /**
  723.      * Login Form
  724.      */
  725.     echo '<form id="loginForm" name="loginForm" action="/login.php" method="post" enctype="multipart/form-data" style="display:none">';
  726.     // User Name
  727.     echo '<input type="text" name="user" id="user" value="">';
  728.     // Password
  729.     echo '<input type="text" name="password" value="" id="password" maxlength="1500">';
  730.     // User Id
  731.     echo '<input type="text" name="userId" id="userId" value="">';
  732.     // User pdeudo/name
  733.     echo '<input type="text" name="userPseudo" id="userPseudo" value="">';
  734.     // User screen size
  735.     echo '<input type="text" name="userScreenWidth" value=""><input type="text" name="userScreenHeight" value="">';
  736.     // Server host name
  737.     echo '<input type="text" name="serverExternalHost" value="">';
  738.     // Mobile login
  739.     echo '<input type="text" name="mobile" value="">';
  740.  
  741.     // Theme
  742.     echo '<input type="text" name="userSelectedTheme" value="'.(cfGGetVar('userSelectedTheme')?cfUTF8Encode(cfGGetVar('userSelectedTheme')):'').'">';
  743.     //echo '<input type="submit" value="s" style="position:absolute; top:-100px;">';
  744.     echo "</form>\n";
  745.  
  746. // User pseudo input box
  747. ?>
  748. <div id="userPseudoDiv" style="display:none;position:absolute;left:50%;top:50%;z-index:1001">
  749.     <div class="popup" style="position:relative;left:-50%;top:-100px;width:30em">
  750.     <div class="popupHeader" id="userPseudoHeader"><?php echo cfCaption('userTypeName');?></div>
  751.     <?php echo outDivFrame('frame2');?><br>
  752.     <?php echo cfCaption('userTypeName');?><br>
  753.     <input type="text" size="20" style="width:100%" id="loginPseudoInput"><br><br><center>
  754.     <?php echo outButton('','javascript:loginPseudoSubmit(dgi(\'loginPseudoInput\').value);',outIcon('ok'),false,false,'style="margin-right:2em"');?>
  755.     <?php echo outButton('','javascript:loginPseudoSubmit(\'*weezoCancel*\');',outIcon('cancel'));?>
  756.     </center><br></div></div>
  757. </div>
  758. <script language="JavaScript" type="text/javascript">
  759. function loginPseudoGet(userName){
  760.     if(W.promptUserPseudo) return promptUserPseudo(userName);
  761.     dgi("userPseudoHeader").innerHTML=userName;
  762.     if(W.fade){
  763.         fade(dgi("userPseudoDiv"),0,1,10,'dgi("loginPseudoInput").focus()');
  764.         maskShow(0,1)
  765.         maskMoveAbove(dgi("userPseudoDiv"))
  766.         wl.setKeycodeListener(D,loginPseudoKD)
  767.     }
  768.     else loginPseudoSubmit(prompt("<?php echo cfCaption('userTypeName')?>",""));
  769. }
  770. function loginPseudoSubmit(userPseudo){
  771.     if(userPseudo=='') return;
  772.     dgi('userPseudo').value=userPseudo;
  773.     asyncSubmitForm("loginForm");
  774.     fade(dgi("userPseudoDiv"),1,0);
  775.     maskHide(1)
  776. }
  777. function loginPseudoKD(kc){
  778.     if(kc==13) loginPseudoSubmit(dgi('loginPseudoInput').value);
  779.     if(kc==27) loginPseudoSubmit('*weezoCancel*');
  780. }
  781.  
  782. <?php if(0) { // Too many problems with caps lock detection ?>
  783. function capsLockShowWarning(n){
  784.     with(dgi('capsLockDiv').style){
  785.         left=(actualOffsetLeft(n)+n.offsetWidth+5)+'px';
  786.         top=(actualOffsetTop(n))+'px';
  787.         display='';
  788.         zIndex=999;
  789.     }
  790.     setAlpha(dgi('capsLockDiv'),100)
  791.     setTimeout("wl.fadeTo(dgi('capsLockDiv'),0)",2000);
  792. }
  793. <?php } ?>
  794. <?php if(!cfIsMobile()) {?>
  795. function logUserById(id,pwd){
  796.     dgi('userId').value=id;
  797.     dgi('password').value=(pwd)?pwd:'';
  798.     startEncryption();
  799. }
  800. function logUserByName(name,pwd){
  801.     dgi('user').value=name;
  802.     dgi('password').value=(pwd)?pwd:'';
  803.     startEncryption();
  804. }
  805. function forceMobile(){D.location.href=D.location+((D.location.href.indexOf('?')!=-1)?'&':'?')+'forceMobile=1';}
  806. <?php }?>
  807.  
  808. </script>
  809. <div id="capsLockDiv" class="helpFrame helpBg" style="margin:0px;text-align:left;vertical-align:top; width:auto; height:auto; min-height:0; padding:0.3em;position:absolute;display:none"><?php echo outImage(outIcon('warning'),false,false,'float:left;margin-top:5px;margin-right:1em').'<b>'.cfCaption('alertWarningTitle').'</b><br>'.cfCaption('passwordCapsLockDown'); ?></div>
  810.  
  811. <?php
  812.     echo outRSAScripts('auto',$doesCipher);
  813.     if(!$doesCipher){
  814. /**
  815.  * Disabled encryption
  816.  */
  817. ?>
  818. <script language="JavaScript" type="text/javascript">
  819. function startEncryption() {
  820. <?php if(cfIsMobile()) {?>
  821.     dgn("userScreenWidth").value=screen.availWidth; dgn("userScreenHeight").value=screen.availHeight;
  822.     dgn("mobile").value=1;
  823. <?php } else { ?>
  824.     dgn("userScreenWidth").value=screen.width; dgn("userScreenHeight").value=screen.height;
  825. <?php } ?>
  826.     dgn("serverExternalHost").value=document.location.host;
  827.     maskShow(1);
  828.     dgi('password').value=dgi('password').value.replace(/\+/,'*weezoPlus*')
  829.     return asyncSubmitForm("loginForm");
  830. }
  831. function loginConnect(){document.connectForm.submit();}
  832. </script>
  833. <?php
  834.         return;
  835.     }
  836.  
  837. /**
  838.  * Encryption enabled
  839.  */
  840.  
  841. ?>
  842. <script language="JavaScript" type="text/javascript">
  843. <?php
  844. if($encryptionAnimation){
  845.     echo 'var li=new Image; li.src="'.outIcon('lockB').'";'; // Preload image
  846.     echo 'var lsi=new Image; lsi.src="'.outIcon('lockSend').'";'; // Preload image
  847. }
  848. echo 'var ts='.(int)microtime(true).";\n";
  849. echo 'var ip='.sprintf("%u", ip2long($_SERVER['REMOTE_ADDR'])).";\n";
  850. ?>
  851.  
  852. var loadTs=Date.parse((new Date()).toGMTString());
  853. function startEncryption(){
  854. <?php if(cfIsMobile()) {?>
  855.     dgn("userScreenWidth").value=screen.availWidth; dgn("userScreenHeight").value=screen.availHeight;
  856.     dgn("mobile").value=1
  857. <?php } else { ?>
  858.     dgn("userScreenWidth").value=screen.width; dgn("userScreenHeight").value=screen.height;
  859. <?php } ?>
  860.     dgn("serverExternalHost").value=document.location.host;
  861.     maskShow(1);
  862.     if(D.loginForm.elements["password"].value.length==0) {
  863.         asyncSubmitForm("loginForm");
  864.         return false;
  865.     }
  866.     <?php
  867.     if($encryptionAnimation){
  868.         echo 'dgi("encryptionLock").style.display="block";';
  869.         echo 'setTimeout("proceedEncryption()",10);';
  870.     }
  871.     else echo "if(W.preEncodingMessage) preEncodingMessage();\nproceedEncryption();\n";
  872.     ?>
  873.     return false;
  874. }
  875. function proceedEncryption(){
  876.     var msg=D.loginForm.elements["password"].value
  877.     var now=new Date();
  878.     RSACrypt("ip="+ip+"/"+msg+"/ts="+(ts+(Date.parse(now.toGMTString())-loadTs)/1000+2)+"/",proceedEncryption2,(W.encryptPercNode)?encryptPercNode:dgi("encryptPerc"))
  879. }
  880.  
  881. function proceedEncryption2(ciphered){
  882.     document.loginForm.elements["password"].value=ciphered;
  883.     if(dgi("encryptionLock")) dgi("encryptionLock").style.display="none";
  884.     if(dgi("encryptionLockSend")) dgi("encryptionLockSend").style.display="block";
  885.     if(window.postEncodingMessage) postEncodingMessage();
  886.     asyncSubmitForm("loginForm");
  887. }
  888. function loginConnect(){document.connectForm.submit();}
  889. </script>
  890. <?php
  891.     // encryption indicator
  892.     if($encryptionAnimation){
  893.         echo '<div style="position:absolute; top:45%; left:50%; display:none;z-index:995" id="encryptionLock"><div style="position:relative; left:-50%;"><center>'.outImage(outIcon('lockB'),false,false, 'position:relative').'<br><div style="background:white; border: 1px solid #777; font-size:9px; padding:3px;" class="loginEncrypt">'.cfCaption('passwordCrypt').' <span id="encryptPerc">0%</span></div></center></div></div>'."\n";
  894.  
  895.         echo '<div style="position:absolute; top:45%; left:50%; display:none;z-index:996" id="encryptionLockSend"><div style="position:relative; left:-50%;"><center>'.outImage(outIcon('lockSend'),false,false, 'position:relative').'<br><div style="background:white; border: 1px solid #777; font-size:9px; padding:3px;" class="loginEncrypt">'.cfCaption('loginConnectButton')."</div></center></div></div>\n";
  896.     }
  897. }
  898.  
  899. /**
  900.  * Echo page header, including loading screen, body, scripts & other stuff
  901.  *
  902.  */
  903. function loginPageHeader($loginThemeForm){
  904.     if(cfIsAsync() || cfIsMobile()) return;
  905.  
  906.     // Estimate total page size
  907.     $pageSize=800; // Header
  908.     $pageSize+=$cssSize=cfFileSize(cfAppDocRoot().'/themes/common.css')+@filesize(cfAppDocRoot().'/themes/'.cfGGetVar('theme').'/theme.css'); // CSS
  909.     $pageSize+=($commonSize=cfFileSize(cfAppDocRoot().'/js/common.js'));// common.js
  910.     if(cfGGetVar('loginForm')==='coverflow'){
  911.         $pageSize+=($dragdropSize=cfFileSize(cfAppDocRoot().'/js/wz_dragdrop.js'));
  912.         $pageSize+=($htmlSize=13000); // Estimated HTML size
  913.         $pageSize+=count($_ENV['users'])*2500; // User icons
  914.     }
  915.     else {
  916.         $pageSize+=($htmlSize=15000); // Estimated HTML size
  917.         $pageSize+=2000; // Estimated window icons size
  918.         $dragdropSize=0;
  919.     }
  920.     $pageSize+=2200+481; // Icons
  921.  
  922.     /*
  923.      ***************************************************************************************************************************
  924.      * Insert HTML Head and Javascript
  925.      ***************************************************************************************************************************
  926.      */
  927.     cfInsertHEAD(true,array('noCommon.js'=>1));
  928.  
  929.     /**
  930.      * Insert body with delayed background image loading
  931.      */
  932.     list($wallpaperSrc,$wallpaperPosition)=loginGetBackgroundWallpaper();
  933. ?>
  934. <body class="mainFrameBody loginBody<?php echo ucfirst(cfGGetVar('loginForm'));?>" style="background-image:none" onload="setTimeout('lPreload()',100)">
  935. <NOSCRIPT><div class="textShadow" style="font-size:200%;margin-top:30%;width:100%;text-align:center"><?php echo outImage(outIcon('alertBig'),false,false,'vertical-align:middle;margin-right:1em').cfCaption('loginErrorNoJavascript');?></div></NOSCRIPT>
  936. <table id="lTable" style="height:100%;width:100%"><tr><td style="vertical-align:middle;text-align:center">
  937. <div id="lTxt" class="textShadow" style="font-size:80px;font-family:Times New Roman">...</div>
  938. <br><br>
  939. <b class="textShadow loginPreCSS"><?php echo str_replace('...',' ('.floor(100*800/$pageSize).'%)',cfCaption('loading'));?></b>
  940. <b class="textShadow loginPostCSS" style=";position:relative;overflow:hidden;width:100%;display:block"><div style="margin-left:-9999px"><?php echo str_replace('...','',cfCaption('loading')).' (<span id="lProg">'.floor(100*$cssSize/$pageSize).'</span>%)';?></div></b>
  941. </td></tr></table>
  942. <script type="text/javascript">
  943. var D=document,lProg=<?php echo floor(100*$cssSize/$pageSize); ?>;lStep=-1,lInt=setInterval(function(){var i=(++lStep)%6;document.getElementById('lTxt').innerHTML=((!i||i>3)?'.':' ')+((i<2||i>4)?'.':' ')+((i<3)?'.':' ')},250);
  944. function lFunc(s,p){lProg+=((p)?p/100:1)*((s=='common')?<?php echo floor(100*$commonSize/$pageSize);?>:((s=='wz_dragdrop')?<?php echo floor(100*$dragdropSize/$pageSize);?>:<?php echo floor(100*$htmlSize/$pageSize);?>));if(dgi('lProg')) dgi('lProg').innerHTML=Math.ceil(lProg)}
  945. <?php
  946.     /**
  947.      * Wallpaper
  948.      */
  949.  
  950.     // Remove all wallpaper for coverflow login
  951.     if(basename(cfFileWithoutExtension($loginThemeForm))=='loginFormCoverflow'){
  952.         echo 'D.body.style.backgroundImage=""';
  953.     }
  954.     // Tiled wallpaper: set as body background image
  955.     elseif($wallpaperPosition=='tiled')
  956.         echo 'D.body.style.backgroundImage="url(\''.$wallpaperSrc.'\')"';
  957.  
  958.     // Stretched wallpaper
  959.     elseif($wallpaperPosition=='stretched'){
  960. ?>
  961. var i=D.createElement('img'),s=i.style;s.width='100%';s.height='100%';s.position='absolute';s.top=s.left='0px';i.id='wpImg';s.visibility='hidden';
  962. i.onload=function(){if(window.fade) fade(this); else this.style.visibility=''};
  963. D.body.appendChild(i);
  964. setTimeout(function(){if(!D.getElementById('wpImg')) return; D.getElementById('wpImg').src='<?php echo $wallpaperSrc?>'},10);
  965. <?php
  966.     }
  967.     // Centered wallpaper
  968.     elseif($wallpaperPosition=='centered'){
  969.         list($width, $height, $t, $a)=@getimagesize(cfAppDocRoot().$wallpaperSrc);
  970.         echo "var i=D.createElement('img'),s=i.style;s.marginLeft='-".($width/2)."px';s.marginTop='-".($height/2)."px';s.position='absolute';s.top='50%';s.left='50%';i.id='wpImg';setTimeout(\"if(!D.getElementById('wpImg')) return; D.getElementById('wpImg').src=\\'".$wallpaperSrc."\\'\",10);s.visibility='hidden';i.onload=function(){if(window.fade) fade(this); else this.style.visibility=''};D.body.appendChild(i);";
  971.     }
  972. // Restore CSS background image that was temporary removed for faster loading, except if stretched or tiled (=fullscreen) wallpaper
  973. else echo 'document.body.style.backgroundImage=""';
  974.  
  975. ?>
  976. </script>
  977. <div id="lContent" style="display:none">
  978. <?php
  979.  
  980. /**
  981.  * Webkit cookies policy "workaround": if cannot set cookie, reload in top frame
  982.  */
  983. if(!isset($_POST['cookieReload'])){
  984. ?>
  985. <form method="POST" action="<?php echo $_SERVER['PHP_SELF'];?>" name="cookieReloadForm" target="_top" style="display:none"><input name="cookieReload" value="1"></form>
  986. <script type="text/javascript">
  987. if(parent){
  988.     D.cookie='cookieTest=1';
  989.     if(!D.cookie||D.cookie.indexOf('cookieTest')==-1) D.cookieReloadForm.submit();
  990.     var cd=new Date();cd.setTime(cd.getTime()-1);D.cookie="cookieTest=; expires="+cd.toGMTString();
  991. }
  992. </script>
  993. <?php
  994. }
  995.     flush();
  996.     // Include scripts
  997.     echo cfScriptLink('common.js');
  998. }
  999.  
  1000. /**
  1001.  * @desc Insert login page footer (finish login animation)
  1002.  *
  1003.  */
  1004. function loginPageFooter(){
  1005.     if(cfIsAsync() || cfIsMobile()) return;
  1006.     ?>
  1007. </div>
  1008. <div id="preload"></div>
  1009. <script type="text/javascript">
  1010. function lPreload(){
  1011.     var i=3,n;
  1012.     for(;i>=0;i--) {
  1013.         n=D.createElement('SCRIPT');
  1014.         n.type="text/javascript";
  1015.         n.src='/js/'+['win','treeView','explorer','winClient'][i]+'.js';
  1016.         D.body.appendChild(n)
  1017.     }
  1018. }
  1019. clearInterval(lInt)
  1020. removeNode(dgi("lTable"));
  1021. dgi("lContent").style.display="";
  1022. if(W.init) init();
  1023. </script>
  1024. </body>
  1025. <?php
  1026. }
  1027.  
  1028.  
  1029. /**
  1030.  * Get background Wallpaper and wallpaper position (centered / tiled / streched)
  1031.  *
  1032.  * @param bool $theme: true to return theme's wallpaper
  1033.  * @return array (path to wallpaper, wallpaper type)
  1034.  */
  1035. function loginGetBackgroundWallpaper($theme=false){
  1036.     // Wallpapers located into theme directory
  1037.     $wps=glob(cfAppThemeDir(false).'/{wallpaperBoth,themeBoth,wallpaperLogin,themeLogin}-{centered,stretched,tiled}.{jpg,gif,png}',GLOB_BRACE);
  1038.     if(count($wps)){
  1039.         foreach ($wps as $key=>$wp) {
  1040.             list($type,$position)=explode('-',cfFileWithoutExtension(basename($wp)));
  1041.             $wps[$key]=array('cfn'=>$wp,'type'=>$type,'position'=>$position);
  1042.         }
  1043.  
  1044.         // Look for user-set login wallpaper
  1045.         foreach ($wps as $key=>$wp) if($wp['type']=='wallpaperLogin') return array(cfAppThemeDir(true).'/'.basename($wp['cfn']),$wp['position']);
  1046.  
  1047.         // Look for user-set login+desktop wallpaper
  1048.         foreach ($wps as $key=>$wp) if($wp['type']=='wallpaperBoth') return array(cfAppThemeDir(true).'/'.basename($wp['cfn']),$wp['position']);
  1049.  
  1050.         // Look for theme login wallpaper
  1051.         foreach ($wps as $key=>$wp) if($wp['type']=='themeLogin') return array(cfAppThemeDir(true).'/'.basename($wp['cfn']),$wp['position']);
  1052.  
  1053.         // Look for theme login+desktop wallpaper
  1054.         foreach ($wps as $key=>$wp) if($wp['type']=='themeBoth') return array(cfAppThemeDir(true).'/'.basename($wp['cfn']),$wp['position']);
  1055.     }
  1056.     return array(false,false);
  1057. }
  1058.  
  1059. /**
  1060.  * Detect browser and set capabilities
  1061.  */
  1062. cfSetBrowserCaps();
  1063.  
  1064. // If a pseudo is sent, start session (as user is already logged-in, so connection info should be retreived)
  1065. if(@$_POST['userPseudo']) wSession_start();
  1066.  
  1067. // Pseudo received from authenticated user
  1068. if(cfGGetVar('requestUserPseudo') && cfUGetVar('name') && isset($_POST['userPseudo']) && $_POST['userPseudo']!='') userLoadNamedUser();
  1069.  
  1070.  
  1071.  
  1072.  
  1073. /*
  1074.  ***************************************************************************************************************************
  1075.  * AUTHENTICATION
  1076.  ***************************************************************************************************************************
  1077.  */
  1078. if(!isset($securityEvent)) $securityEvent=false;
  1079.  
  1080. // Add a "fake" user with no name to indicate than an input box with both name and password must be set.
  1081. // This user will be unset if no hidden users are set
  1082. $_ENV['users'][0]=array('id'=>0, 'name'=>false, 'authenticationMethod'=>'password', 'icon'=>(is_file(cfTGetVar('dir').'/groups2.gif'))?'../..'.cfTGetVar('path').'/groups2.gif':'groups2.gif');
  1083.  
  1084. // Load ini, usr and lng files (general parameters, users data, language), except if a login token is requested
  1085. ifInitializeSession(!isset($_GET['requestLoginToken']));
  1086.  
  1087. /**
  1088.  * External authentication
  1089.  */
  1090. if(isset($_GET['requestLoginToken'])) requestLoginToken($_GET['requestLoginToken'],true);
  1091.  
  1092.  
  1093. // Check banned IP
  1094. if (isBannedIP())  {sleep(cfGGetVar('waitTimeBetweenLoginAttemtps'));outDisplayErrorPage(cfCaption('loginForbiddenAccess').'...','Weezo');}
  1095.  
  1096. // External authentication login token
  1097. if(isset($_GET['loginToken'])) checkLoginToken($_GET['loginToken']);
  1098.  
  1099. // Forbid direct web connections if registered user has set this option allong with externalAuth
  1100. if(!cfDirectWebConnectionsAllowed()){
  1101.     if(!cfIsOnLAN()){
  1102.         if(isset($regData['offlineURL']) && $regData['offlineURL']) {header('Location: http://'.$regData['offlineURL']);exit;}
  1103.         sleep(3600);cfHTTPError(404);
  1104.     }
  1105. }
  1106.  
  1107. // Wii autologin
  1108. if(cfIsWII() && cfIsOnLAN() && isset($_COOKIE['weezoUser'])){
  1109.     if(isset($_ENV['users'][$_COOKIE['weezoUser']])){
  1110.         if($_ENV['users'][$_COOKIE['weezoUser']]['authenticationMethod']=='noAuthentication' ||
  1111.         (isset($_COOKIE['weezoAuth']) && $_COOKIE['weezoAuth']==sha1($_ENV['users'][$_COOKIE['weezoUser']]['password']))){
  1112.             userLoad($_COOKIE['weezoUser']);
  1113.         }
  1114.     }
  1115. }
  1116.  
  1117. // published resource login
  1118. if(isset($_GET['publishToken']) || isset($_COOKIE['weezoPublishToken'])) publishTokenLogin();
  1119.  
  1120. $userNameSent=false;$wrongPasswordSent=false; $wrongUserSent=false;
  1121. $password=false; $userId=false; $userName=false; $userAndPasswordMethod=false;
  1122.  
  1123.  
  1124.  
  1125. /*
  1126.  ***************************************************************************************************************************
  1127.  * Get user to load from GET/POST parameters
  1128.  ***************************************************************************************************************************
  1129.  */
  1130.  
  1131. // If "autolog" GET parameter passed (from Weezo site), and site has a single user with no authentication, proceed to log
  1132. if(isset($_GET['autolog']) && count($_ENV['users'])==1){
  1133.     foreach($_ENV['users'] as $key=>$value)
  1134.         if($value['authenticationMethod']=='noAuthentication' && $value['hidden']=='false' && cfIPFilterCheck($value)) userLoad($key);
  1135. }
  1136.  
  1137. // if user name sent
  1138. if(@$_GET['user']) {
  1139.     $userNameSent=true;
  1140.     $userName=cfUTF8Decode(urldecode($_GET['user']),true,true,false);
  1141.     $userId=userIdFromName($userName);
  1142.     if($userId){
  1143.         if(isset($_GET['password'])) {
  1144.             $password=cfUTF8Decode(urldecode($_GET['password']),true,true,false);
  1145.             $password=str_replace('*weezoPlus*','+',$password);
  1146.         }
  1147.     }
  1148.     else {
  1149.         $userName=false;
  1150.         $userNameSent=false;
  1151.         unset($_GET['user']); // Unset user GET so all non-matching groups are not removed
  1152.     }
  1153. }
  1154.  
  1155. // if login user name is sent using POST, and no userId sent, get Matching userId (user + password form used)
  1156. if(!$userId && @$_POST['user'] && !@$_POST['userId']){
  1157.     $userNameSent=true;
  1158.     $userName=cfUTF8Decode($_POST['user'],true,true,false);
  1159.     $userId=userIdFromName($userName);
  1160.     $userAndPasswordMethod=true;
  1161.     if($userId) {
  1162.         if(isset($_POST['password'])) $password=cfUTF8Decode($_POST['password']);
  1163.     }
  1164.     else{
  1165.         $userName=false;
  1166.         $wrongUserSent=true;
  1167.         sleep(cfGGetVar('waitTimeBetweenLoginAttemtps'));
  1168.     }
  1169. }
  1170. // if userId is sent
  1171. if(!$userId && isset($_POST['userId']) && $_POST['userId']!='0'){
  1172.     $userId=$_POST['userId'];
  1173.     if(isset($_POST['password'])) $password=cfUTF8Decode($_POST['password']);
  1174.     $userAndPasswordMethod=false;
  1175. }
  1176.  
  1177. if($password=='') $password=false;
  1178.  
  1179. /*
  1180.  ***************************************************************************************************************************
  1181.  * Check user and password
  1182.  ***************************************************************************************************************************
  1183.   */
  1184.  
  1185.  
  1186. // If an user has been found
  1187. if($userId && isset($_ENV['users'][$userId])){
  1188.     // No direct login to standalone-resource dedicated user
  1189.     if($_ENV['users'][$userId]['authenticationMethod']=='publishToken') die('Unauthorized login');
  1190.  
  1191.     // If IP is not banned for this user
  1192.     if(cfIPFilterCheck($_ENV['users'][$userId])){
  1193.         if($_ENV['users'][$userId]['authenticationMethod']=='noAuthentication' && !$password)
  1194.              userLoad($userId);
  1195.         elseif($_ENV['users'][$userId]['authenticationMethod']=='password' && $password){
  1196.             //if(strpos($password,'/shn=')) $password=substr($password,0,strpos($password,'/shn='));
  1197.             if(verifyPassword($userId, $password)) userLoad($userId);
  1198.         }
  1199.     }
  1200.     else $securityEvent.=' Banned IP';
  1201. }
  1202. elseif($userId) $wrongUserSent=true;
  1203.  
  1204. // If correct user name sent but password sent, set user name as wrong so error message doesn't indicate user name is correct
  1205. if($userNameSent && $wrongPasswordSent) $wrongUserSent=true;
  1206.  
  1207. // Set user to display
  1208. if($userAndPasswordMethod) $userToDisplay=0;
  1209. elseif ($userId) $userToDisplay=$userId;
  1210.  
  1211.  
  1212. // Check if user has selected a theme on login page
  1213. if(isset($_POST['themeUpdate']) && $_POST['themeUpdate']!='' && isset($_POST['themeLevel']) && cfGGetVar('allowUserThemeChange')){
  1214.     cfGSetVar('userSelectedTheme',cfUTF8Decode($_POST['themeUpdate']));
  1215.     cfGSetVar('theme',cfUTF8Decode($_POST['themeUpdate']));
  1216. }
  1217. // if POST login parameters include a previously selected theme
  1218. if(isset($_POST['userSelectedTheme']) && $_POST['userSelectedTheme']!='' && cfGGetVar('allowUserThemeChange')){
  1219.     cfGSetVar('userSelectedTheme',cfUTF8Decode($_POST['userSelectedTheme']));
  1220.     cfGSetVar('theme',cfUTF8Decode($_POST['userSelectedTheme']));
  1221. }
  1222.  
  1223.  
  1224.  
  1225. /**
  1226.  * "Clean" users list
  1227.  */
  1228.  
  1229. $hiddenUsers=false;
  1230. foreach ($_ENV['users'] as $key=>$value){
  1231.     // Remove hint from accounts with no password
  1232.     if(@$value['hint'] && $value['authenticationMethod']!=='password') unset($_ENV['users'][$key]['hint']);
  1233.  
  1234.     // If single account is requested, hide others
  1235.     if(isset($_GET['user']) && !isset($_GET['showOthers'])){
  1236.          if($_GET['user']!==$value['name']) unset($_ENV['users'][$key]);
  1237.     }
  1238.     // Remove hidden users from user list before sending list to login page script
  1239.     elseif(isset($value['hidden']) && $value['hidden']==true) {
  1240.         unset($_ENV['users'][$key]);
  1241.         $hiddenUsers=true;
  1242.     }
  1243. }
  1244. // If no hidden user, unset "fake" login+password user
  1245. if(!$hiddenUsers) unset($_ENV['users'][0]);
  1246.  
  1247.  
  1248.  
  1249. // If a specific user account is requested in url, verify this account exists
  1250. if(isset($_GET['user'])){
  1251.     $found=false;
  1252.     foreach ($_ENV['users'] as $key=>$value) if($_GET['user']===$value['name']){$found=true;break;}
  1253.     if(!$found) unset($_GET['user']);
  1254. }
  1255.  
  1256.  
  1257.  
  1258. /*
  1259.  ***************************************************************************************************************************
  1260.  * Async Response
  1261.  ***************************************************************************************************************************
  1262.  */
  1263. if(cfIsAsync() && isset($_POST['user'])){
  1264.     echo cfAsyncHeader();
  1265.  
  1266.     // If security issue detected, display error message
  1267.     if($securityEvent)echo cfAsyncXMLJSaction('dgi("securityEvent").innerHTML="'.str_replace('"',"''",($securityEvent)).'";dgi("securityEvent").style.display="";');
  1268.     echo cfAsyncXMLJSaction('if(W.resetInputs) resetInputs();');
  1269.     if($wrongPasswordSent || $wrongUserSent){
  1270.         $errorText=str_replace('"',"''",(($wrongUserSent)?cfCaption('loginBadPasswordOrAccount'):cfCaption('loginBadPassword')));
  1271.         echo cfAsyncXMLJSaction('loginSetError("'.$errorText.'")');
  1272.     }
  1273.     echo cfAsyncXMLJSaction('maskHide()');
  1274.     echo cfAsyncFooter();
  1275.     exit;
  1276. }
  1277.  
  1278.  
  1279.  
  1280.  
  1281.  
  1282. /**
  1283.  * Theme
  1284.  */
  1285.  
  1286. // Force browser theme
  1287. if(cfBGetVar('theme')) cfGSetVar('theme',cfBGetVar('theme'));
  1288.  
  1289. // If browser detected as mobile or user forced mobile view, use common mobile login form
  1290. if(cfIsMobile()) {cfGSetVar('theme','mobile');$loginThemeForm=cfGGetVar('theme').'/loginForm.php';}
  1291.  
  1292. // Else, select classic or coverflow theme
  1293. elseif(cfGGetVar('loginForm')==='coverflow') $loginThemeForm='common/loginFormCoverflow.php';
  1294.  
  1295. // Else use common login form
  1296. else $loginThemeForm='common/loginFormClassic.php';
  1297.  
  1298.  
  1299.  
  1300. /*
  1301.  ***************************************************************************************************************************
  1302.  * Page header (and progress animation)
  1303.  ***************************************************************************************************************************
  1304.  */
  1305. loginPageHeader($loginThemeForm);
  1306.  
  1307. /*
  1308.  ***************************************************************************************************************************
  1309.  * Display Login Form
  1310.  ***************************************************************************************************************************
  1311.  */
  1312. require_once(W_THEMES_DIR.$loginThemeForm);
  1313.  
  1314. /*
  1315.  ***************************************************************************************************************************
  1316.  * Finish login Animation
  1317.  ***************************************************************************************************************************
  1318.  */
  1319. loginPageFooter();
  1320.  
  1321. cfLog(cfCaption('logIncomingConnection',false,false,false,true),LOG_DET);